module CanCamel
  class Linter
    LintingError = Class.new(StandardError)

    def lint
      Cache.reload! rescue return
      %i(lint_nodes lint_filters).reduce(true) { |base, x| base && send(x) }
    end

    def lint!
      raise LintingError unless lint
    end

    def lint_node(node)
      node = node.dup
      node.inherit!
      %i(validate_node).reduce(true) { |base, x| base && send(x, node) }
    end

    def lint_filters
      CanCamel::Filter.filters.values.flatten.uniq.each { |filter| !filter.respond_to?(:lint!) || filter.lint! }
      true
    rescue CanCamel::Linter::LintingError
      false
    end

    private

    def validate_node(node)
      node.condition.each do |method, args|
        Validators.validate!(filter: method, args: args.symbolize_keys, path: node.path)
      end
      true
    rescue Validators::ValidationError, LintingError
      false
    end

    def lint_nodes
      CanCamel::Node.all.reduce(true) { |base, x| base && lint_node(x) }
    end
  end
end
